package com.forecasting.statistic;

import static com.forecasting.utility.Utility.*;

import java.io.Serializable;
import java.text.NumberFormat;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.forecasting.interfaces.Distribution;
import com.forecasting.model.PartNumber;
import com.forecasting.utility.Utility;

public class PoissonDistribution implements Distribution,Serializable {
	private int rop = 0;
	
	private PartNumber pn = null;
	private double lambda = 0;
	private double L = 0;
	private double serviceLevel = 0;
		
	public PoissonDistribution(PartNumber partnumber){
		this.pn = partnumber;
		this.lambda = pn.getForecast() * pn.getLeadtime();
		this.L = Math.exp(-lambda); 
		this.serviceLevel = calcOriginalServicelevel();
	}
	private double calcOriginalServicelevel(){
		/* Exposant = Math.pow(x,y)*/
		double sum = 0;
		for(int i = 0;i <= pn.getRop(); i++){
			//System.out.println("i" + i + ":" + getProbability(i));
			//System.out.println("sum i" + i + ":" + sum);
			sum = sum + getProbability(i);
		}
		return sum;	
	}
	private double getProbability(int rop){ 
		double p = 0;
		p = (L * Math.pow(lambda, rop))/getFactorial(rop); 
		return p;
	}
	@Override
	public double changeRop(int reorderPoint) {
		this.pn.setRop(reorderPoint);
		this.serviceLevel = calcOriginalServicelevel();
		return this.serviceLevel;
	}
	public void recalculateServiveLevel(){
		this.serviceLevel = calcOriginalServicelevel();
	}
	@Override
	public double getServiceLevel() {
		return serviceLevel;
	}
	public int getCalculatedROP(double serviceLevel){
		
		return calcRop( serviceLevel);
	}
	private int calcRop(double sl){
		/* Exposant = Math.pow(x,y)*/
		double sum = 0;
		int ropSL = 0;
		//returns the ROP with probability highest but lower than request service level
		do{
			sum = sum + getProbability(ropSL);
			ropSL++;	
		}while(Utility.formatDecimal(sum, 4) < sl);
		//System.out.println("prob :"+ sum  + " i: " + ropSL ) ;
		ropSL -= 1;
		
		return ropSL;
	}

	public String toString(){
		String resStr = pn.toString() + "\n";
		resStr =  resStr + "Forecast: " + pn.getForecast() + " Leadtime: " + pn.getLeadtime() + "\nROP: " + 
		pn.getRop() + " Service level: " + formatDecimal(getServiceLevel(),4) * 100 +"%\n";
		return resStr;
	}

}



